home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / asmbler.arc / BUF160.ASM < prev    next >
Assembly Source File  |  1988-11-19  |  11KB  |  263 lines

  1.  
  2. VECTORS         SEGMENT AT 0H
  3.         ORG     9H*4
  4. KEYBOARD_INT_VECTOR     LABEL   DWORD
  5.         ORG     16H*4
  6. KEYBOARD_IO_VECTOR      LABEL   DWORD
  7. VECTORS         ENDS
  8.  
  9. ROM_BIOS_DATA   SEGMENT AT 40H
  10.         ORG     17H
  11. KBD_FLAG        DB      ?
  12.         ORG     1AH
  13. ROM_BUFFER_HEAD DW      ?
  14. ROM_BUFFER_TAIL DW      ?
  15. KB_BUFFER       DW      16D DUP (?)
  16. KB_BUFFER_END   LABEL   WORD
  17. ROM_BIOS_DATA   ENDS
  18. CODE_SEG        SEGMENT
  19.         ASSUME  CS:CODE_SEG
  20.         ORG     100H
  21. BEGIN:  JMP     INIT_VECTORS            ;Initialize vectors and attach to DOS
  22. ROM_KEYBOARD_INT        DD
  23. ROM_KEYBOARD_IO         DD
  24. BUFFER_HEAD             DW      OFFSET KEYBOARD_BUFFER
  25. BUFFER_TAIL             DW      OFFSET KEYBOARD_BUFFER
  26. KEYBOARD_BUFFER         DW      160D DUP(0)     ;159 character input buffer
  27. KEYBOARD_BUFFER_END     LABEL   WORD
  28.  
  29. ;--------------------------------------------------------;
  30. ; This procedure sends a short beep when the buffer fills
  31. ;--------------------------------------------------------;
  32.  
  33. KB_CONTROL      EQU     61H             ;Control bits for keyboard & speaker
  34. ERROR_BEEP      PROC    NEAR
  35.         PUSH    AX
  36.         PUSH    BX
  37.         PUSH    CX
  38.         PUSHF                           ;Save old interupt enable flag
  39.         CLI                             ;Turn off beep during interupt
  40.         MOV     BX,30D                  ;Number of cycles for 1/8 second tone
  41.         IN      AL,KB_CONTROL           ;Get information from speaker port
  42.         PUSH    AX                      ;Save control information
  43. START_OF_ONE_CYCLE:
  44.         AND     AL,0FCH                 ;Turn off speaker
  45.         OUT     KB_CONTROL,AL
  46.         MOV     CX,60D                  ;Delay for one half cycle
  47. OFF_LOOP:
  48.         LOOP    OFF_LOOP
  49.         OR      AL,2                    ;Turn off speaker
  50.         OUT     KB_CONTROL,AL
  51.         MOV     CX,60D                  ;Delay for second half cycle
  52. ON_LOOP:
  53.         LOOP    ON_LOOP
  54.         DEC     BX                      ;200 cycles yet?
  55.         JNZ     START_OF_ONE_CYCLE
  56.         POP     AX                      ;Recover old keyboard information
  57.         OUT     KB_CONTROL,AL
  58.         POPF                            ;Restore interupt flag
  59.         POP     CX
  60.         POP     BX
  61.         POP     AX
  62.         RET
  63. ERROR_BEEP      ENDP
  64.  
  65. ;This procedure checks the ROM keyboard buffer to see if some program
  66. ;tried to clear this buffer. We know it's been cleared when the ROM
  67. ;tail and header overlap. Normally, the new procedures below keep the
  68. ;dummy character, word 0,in the buffer.
  69. ;
  70. ;Uses: BX,DS
  71. ;Writes:        BUFFER_HEAD,BUFFER_TAIL,ROM_BUFFER_HEAD,
  72. ;               ROM_BUFFER_TAIL
  73. ;Reads:         KEYBOARD_BUFFER,KB_BUFFER
  74.  
  75. CHECK_CLEAR_BUFFER      PROC NEAR
  76.         ASSUME  DS:ROM_BIOS_DATA
  77.         MOV     BX,ROM_BIOS_DATA        ;Establish pointer to BIOS data
  78.         MOV     DS,BX
  79.         CLI                             ;Turn off interupts during this check
  80.         MOV     BX,ROM_BUFFER_HEAD      ;check to see if buffer cleared
  81.         CMP     BX,ROM_BUFFER_TAIL      ;Is the buffer empty?
  82.         JNE     BUFFER_OK               ;No, then everything is alright
  83.                                         ;Yes, then clear the internal buffer
  84.         MOV     BX,OFFSET KB_BUFFER     ;Reset buffer with word 0 in buffer
  85.         MOV     ROM_BUFFER_HEAD,BX
  86.         ADD     BX,2
  87.         MOV     ROM_BUFFER_TAIL,BX
  88.         ASSUME  DS:CODE_SEG
  89.         MOV     BX,CS
  90.         MOV     DS,BX
  91.         MOV     BX,OFFSET KEYBOARD_BUFFER ;Reset internal buffer
  92.         MOV     BUFFER_HEAD,BX
  93.         MOV     BUFFER_TAIL,BX
  94. BUFFER_OK:
  95.         ASSUME  DS:CODE_SEG
  96.         STI                             ;Interupts back on
  97.         RET
  98. CHECK_CLEAR_BUFFER      ENDP
  99.  
  100. ;This procedure intercepts the keyboard interrupt and moves any new
  101. ;characters to the internal, 80 character buffer.
  102.  
  103. INTERCEPT_KEYBOARD_INT  PROC    NEAR
  104.         ASSUME  DS:NOTHING
  105.         PUSH    DS
  106.         PUSH    SI
  107.         PUSH    BX
  108.         PUSH    AX
  109.         CALL    CHECK_CLEAR_BUFFER      ;Check for buffer cleared
  110.         PUSHF
  111.         CALL    ROM_KEYBOARD_INT        ;Read scan code with BIOS routines
  112. ;-----  Transfer any characters to internal buffer
  113.         ASSUME  DS:ROM_BIOS_DATA
  114.         MOV     BX,ROM_BIOS_DATA        ;Establish pointer to BIOS data
  115.         MOV     DS,BX
  116.         MOV     SI,BUFFER_TAIL
  117.         MOV     BX,ROM_BUFFER_HEAD      ;Check if real characters in buffer
  118.         INC     BX                      ;Skip over dummy character
  119.         INC     BX
  120.         CMP     BX,OFFSET KB_BUFFER_END
  121.         JB      DONT_WRAP               ;No need to wrap the pointer
  122.         MOV     BX,OFFSET KB_BUFFER     ;Wrap the pointer
  123. DONT_WRAP:
  124.         CMP     BX,ROM_BUFFER_TAIL      ;Is there a real character?
  125.         JE      NO_NEW_CHARACTERS       ;No then return to caller
  126.         MOV     AX,[BX]                 ;Yes,move character to internal buffer
  127.         MOV     CS:[SI],AX
  128.         INC     SI
  129.         INC     SI                      ;Move to next position
  130.         CMP     SI,OFFSET KEYBOARD_BUFFER_END
  131.         JB      NOT_AT_END
  132.         MOV     SI,OFFSET KEYBOARD_BUFFER
  133. NOT_AT_END:
  134.         CMP     SI,BUFFER_HEAD          ;Buffer overrun?
  135.         JNE     WRITE_TO_BUFFER         ;Yes beep and throw out character
  136.         CALL    ERROR_BEEP
  137.         JMP     SHORT NOT_AT_KB_END
  138. WRITE_TO_BUFFER:
  139.         MOV     BUFFER_TAIL,SI
  140. NOT_AT_KB_END:
  141.         MOV     ROM_BUFFER_HEAD,BX
  142.  
  143. NO_NEW_CHARACTERS:
  144. ;----   See if CTRL + ALT pushed, and clear buffer if so
  145.  
  146.         MOV     AL,KBD_FLAG             ;Get status of shift keys into AL
  147.         AND     AL,0CH                  ;Isolate Alt and Crtl shift flags
  148.         CMP     AL,0CH                  ;Are both the Alt and Crtl keys down?
  149.         JNE     DONT_CLEAR_BUFFER       ;No, then dont clear the buffer
  150.         MOV     AX,BUFFER_TAIL          ;Yes, then clear the buffer
  151.         MOV     BUFFER_HEAD,AX
  152.  
  153. DONT_CLEAR_BUFFER:
  154.         POP     AX
  155.         POP     BX
  156.         POP     SI
  157.         POP     DS
  158.         IRET
  159. INTERCEPT_KEYBOARD_INT ENDP
  160.  
  161. ;-----------------------------------------------------------------------;
  162. ;This procedure replaces the ROM BIOS routines for reading a character  ;
  163. ;-----------------------------------------------------------------------;
  164.         ASSUME  DS:CODE_SEG
  165. INTERCEPT_KEYBOARD_IO PROC      FAR
  166.         STI                             ;Interrupts back on
  167.         PUSH    DS                      ;Save current DS
  168.         PUSH    BX                      ;Save BX temporarily
  169.         CALL    CHECK_CLEAR_BUFFER      ;Check for buffer cleared
  170.         MOV     BX,CS                   ;Establish pointer to data area
  171.         MOV     DS,BX
  172.         OR      AH,AH                   ;AH=0?
  173.         JZ      READ_CHARACTER          ;Yes, read a character
  174.         DEC     AH                      ;AH=1?
  175.         JZ      READ_STATUS             ;Yes, return the status
  176.         DEC     AH                      ;AH=2?
  177.         JZ      READ_SHIFT_STATUS       ;Yes, return shift status
  178.         POP     BX                      ;Ignore the other function numbers
  179.         POP     DS
  180.         IRET
  181.  
  182. ;----   Read the key
  183.  
  184. READ_CHARACTER:                         ;ASCII read
  185.         STI                             ;Interrupts back on during loop
  186.         NOP                             ;Allow an interrupt to occur
  187.         CLI                             ;Interrupts back off
  188.         MOV     BX,BUFFER_HEAD          ;Get pointer to head of buffer
  189.         CMP     BX,BUFFER_TAIL          ;Test end of buffer
  190.         JE      READ_CHARACTER          ;Loop until something in buffer
  191.         MOV     AX,[BX]                 ;Get scan code and ASCII code
  192.         ADD     BX,2                    ;Move to next word in buffer
  193.         CMP     BX,OFFSET KEYBOARD_BUFFER_END   ;At end of buffer?
  194.         JNE     SAVE_POINTER            ;No, continue
  195.         MOV     BX,OFFSET KEYBOARD_BUFFER       ;Yes, reset to buffer start
  196. SAVE_POINTER:
  197.         MOV     BUFFER_HEAD,BX          ;Store value in variable
  198.         POP     BX
  199.         POP     DS
  200.         IRET                            ;Return to caller
  201.  
  202. ;----   ASCII status
  203.  
  204. READ_STATUS:
  205.         CLI                             ;Interrupts off
  206.         MOV     BX,BUFFER_HEAD          ;Get head pointer
  207.         CMP     BX,BUFFER_TAIL          ;If equal (ZF=1) then nothing there
  208.         MOV     AX,[BX]
  209.         STI                             ;Interrupts back on
  210.         POP     BX                      ;Recover registers
  211.         POP     DS
  212.         RET     2                       ;Throw away flags
  213.  
  214. READ_SHIFT_STATUS:
  215.         JMP     ROM_KEYBOARD_IO         ;Let ROM routines do this
  216. INTERCEPT_KEYBOARD_IO   ENDP
  217.  
  218. ;-----------------------------------------------------------------;
  219. ;This procedure initializes the interrupt vectors.                ;
  220. ;-----------------------------------------------------------------;
  221. INIT_VECTORS    PROC    NEAR
  222.         ASSUME  DS:VECTORS
  223.         PUSH    DS                      ;Save old Data Segment
  224.         MOV     AX,VECTORS              ;Set up the data segment for vectors
  225.         MOV     DS,AX
  226.         CLI                             ;Dont allow interrupts
  227.  
  228.         MOV     AX,KEYBOARD_INT_VECTOR  ;Save addresses of BIOS routines
  229.         MOV     ROM_KEYBOARD_INT,AX
  230.         MOV     AX,KEYBOARD_INT_VECTOR[2]
  231.         MOV     ROM_KEYBOARD_INT[2],AX
  232.                                         ;Set up new KEYBOARD_INT vector
  233.         MOV     KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
  234.         MOV     KEYBOARD_INT_VECTOR[2],CS
  235.         STI                             ;Allow interrupts again
  236.                                         ;Set up KEYBOARD_IO vector
  237.         MOV     AX,KEYBOARD_IO_VECTOR
  238.         MOV     ROM_KEYBOARD_IO,AX
  239.         MOV     AX,KEYBOARD_IO_VECTOR[2]
  240.         MOV     ROM_KEYBOARD_IO[2],AX
  241.         MOV     KEYBOARD_IO_VECTOR,OFFSET INTERCEPT_KEYBOARD_IO
  242.         MOV     KEYBOARD_IO_VECTOR[2],CS
  243.                                         ;Now set up the the kbd buffer, etc.
  244.  
  245.         ASSUME  DS:ROM_BIOS_DATA
  246.         MOV     AX,ROM_BIOS_DATA
  247.         MOV     DS,AX
  248.         CLI                             ;Dont allow interrupts now
  249.         MOV     BX,OFFSET KB_BUFFER
  250.         MOV     ROM_BUFFER_HEAD,BX
  251.         MOV     WORD PTR [BX],0
  252.         ADD     BX,2
  253.         MOV     ROM_BUFFER_TAIL,BX
  254.         STI                             ;Allow interrupts again
  255.  
  256.         MOV     DX,OFFSET INIT_VECTORS  ;End of resident portions
  257.         INT     27H                     ;Terminate but stay resident
  258. INIT_VECTORS    ENDP
  259.  
  260. CODE_SEG        ENDS
  261.  
  262.         END     BEGIN
  263.